/*
 *    Thing Game Library
 *   Copyright (C)2005 - 2010 Eduardo Nunes Pereira (eduardonunesp at gmail dot com)
 *
 *   This program/library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 *   This program/library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 *    You should have received a copy of the GNU Lesser General Public
 * License along with this program/library ; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */


#include <algorithm>
#include "EventManager.hpp"
#include "Window.hpp"
#include "Keyboard.hpp"
#include "Mouse.hpp"
#include "Format.hpp"
#include "Globals.hpp"

void Thing::Events::EventManager::initialize()
{
    DBG("Trying to initialize inputs");

    _window = new Window();
    _keyboard = new Keyboard();
    _mouse = new Mouse();

    DBG("Eventss initialized");
}

Thing::Events::EventManager::~EventManager()
{
    DBG("Cleaning inputs");

    delete _window;
    delete _keyboard;
    delete _mouse;
}

void Thing::Events::EventManager::update()
{
    try
    {
        while(SDL_PollEvent(&_event))
        {
            switch(_event.type)
            {
                case SDL_QUIT:
                    _window->setWindowState(Window::State::QUITTING);
                    break;
                case SDL_ACTIVEEVENT:
                    
                    if(_event.active.gain)
                        _window->setWindowState(Window::State::HAS_FOCUS);
                    else if(!_event.active.gain)
                        _window->setWindowState(Window::State::NO_FOCUS);
                    
                    break;
                case SDL_KEYDOWN:
                    _keyboard->setKeyState(Keyboard::Key::KeyState::PRESSED, 
                                           _event.key.keysym.sym);
                    break;
                case SDL_KEYUP:
                    _keyboard->setKeyState(Keyboard::Key::KeyState::RELEASED,
                                           _event.key.keysym.sym);
                    break;
                case SDL_MOUSEMOTION:
                    _mouse->setMousePos(_event.motion.x, _event.motion.y);
                    break;
                case SDL_MOUSEBUTTONDOWN:
                    _mouse->setButtonState(Mouse::Button::ButtonState::PRESSED,
                                           _event.button.button);
                    break;
                case SDL_MOUSEBUTTONUP:
                    _mouse->setButtonState(Mouse::Button::ButtonState::RELEASED,
                                           _event.button.button);
                    break;
                default:
                    throw EventsException(EventsException::UNKNOW_EVENT, 
                        STG(FMT("Event not identified [%d]") % _event.type));
            }
        }
    }catch(EventsException &ie)
    {
        DBG(ie.what());
    }
}

void Thing::Events::EventManager::showMouseCursor(bool show)
{ 
    _mouse->showCursor(show); 
}

bool Thing::Events::EventManager::onWindowQuit()
{
    if(_window->checkWindowState() == Window::State::QUITTING)
    {
        DBG("Window quitting !");

        _window->clearState();
        return true;
    }
    else
        return false;
}

bool Thing::Events::EventManager::onKeyPressed(int k)
{
    if(_keyboard->checkKeyState(k) == Keyboard::Key::KeyState::PRESSED)
    {
        DBG(STG(FMT("Key [%s] pressed") % Keyboard::Key::keyToString(k)));

        _keyboard->clearState(k);
        return true;
    }
    else 
        return false;
}

bool Thing::Events::EventManager::onKeyReleased(int k)
{
    if(_keyboard->checkKeyState(k) == Keyboard::Key::KeyState::RELEASED)
    {
        DBG(STG(FMT("Key [%s] released") % Keyboard::Key::keyToString(k)));

        _keyboard->clearState(k);
        return true;
    }
    else 
        return false;
}
